/**
 * @file quality_descriptors.c
 * @brief 品质描述符处理实现
 * @details 本文件实现了104协议中各种品质描述符的解析和构建功能，
 *          包括SIQ、DIQ、QDS、DCO等品质描述符的处理。
 * 
 * @author zyb
 * @date 2025-10-01
 * @version 1.0
 * 
 * @note 品质描述符的位定义严格按照IEC 60870-5-104协议规范
 * @warning 位域结构在不同编译器下可能有不同的内存布局
 * 
 * @see protocol_types.h
 * @see constants.h
 * @see error_codes.h
 */

#include "quality_descriptors.h"
#include "protocol_types.h"
#include "constants.h"
#include "../../error/include/error_codes.h"
#include "../../../common/logs/include/logger.h"
#include <string.h>

// 定义模块名称
#define LOG_MODULE_NAME "QUALITY_DESCRIPTORS"

/* ==================== SIQ处理函数实现 ==================== */

/**
 * @brief 解析SIQ品质描述符
 * @details 从字节流中解析SIQ品质描述符，按照协议规范解析各个位域
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param offset 偏移量
 * @param siq SIQ结构输出，不能为NULL
 * @return 协议错误码
 */
protocol_error_t parse_siq(const uint8_t* buffer, size_t buffer_size, size_t offset, siq_t* siq) {
    if (buffer == NULL || siq == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (offset >= buffer_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区偏移量超出范围");
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    uint8_t byte = buffer[offset];
    
    // 按照协议规范解析位域
    siq->spi = byte & 0x01;           // Bit 1: 单点信息位
    siq->reserved = (byte >> 1) & 0x07; // Bit 4-2: 保留位
    siq->bl = (byte >> 5) & 0x01;     // Bit 5: 闭锁位
    siq->sb = (byte >> 6) & 0x01;     // Bit 6: 替代位
    siq->nt = (byte >> 7) & 0x01;     // Bit 7: 非当前值位
    siq->iv = (byte >> 8) & 0x01;     // Bit 8: 无效位
    
    LOG_DEBUG(LOG_MODULE_NAME, "SIQ解析: 0x%02X -> SPI=%d, BL=%d, SB=%d, NT=%d, IV=%d", 
              byte, siq->spi, siq->bl, siq->sb, siq->nt, siq->iv);
    
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 构建SIQ品质描述符
 * @details 将SIQ结构转换为字节流，按照协议规范构建各个位域
 * 
 * @param siq SIQ结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param offset 偏移量
 * @return 协议错误码
 */
protocol_error_t build_siq(const siq_t* siq, uint8_t* buffer, size_t offset) {
    if (siq == NULL || buffer == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    uint8_t byte = 0;
    
    // 按照协议规范构建位域
    byte |= (siq->spi & 0x01);                    // Bit 1: 单点信息位
    byte |= ((siq->reserved & 0x07) << 1);        // Bit 4-2: 保留位
    byte |= ((siq->bl & 0x01) << 5);              // Bit 5: 闭锁位
    byte |= ((siq->sb & 0x01) << 6);              // Bit 6: 替代位
    byte |= ((siq->nt & 0x01) << 7);              // Bit 7: 非当前值位
    byte |= ((siq->iv & 0x01) << 8);              // Bit 8: 无效位
    
    buffer[offset] = byte;
    
    LOG_DEBUG(LOG_MODULE_NAME, "SIQ构建: SPI=%d, BL=%d, SB=%d, NT=%d, IV=%d -> 0x%02X", 
              siq->spi, siq->bl, siq->sb, siq->nt, siq->iv, byte);
    
    return PROTOCOL_SUCCESS;
}

/* ==================== DIQ处理函数实现 ==================== */

/**
 * @brief 解析DIQ品质描述符
 * @details 从字节流中解析DIQ品质描述符，按照协议规范解析各个位域
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param offset 偏移量
 * @param diq DIQ结构输出，不能为NULL
 * @return 协议错误码
 */
protocol_error_t parse_diq(const uint8_t* buffer, size_t buffer_size, size_t offset, diq_t* diq) {
    if (buffer == NULL || diq == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (offset >= buffer_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区偏移量超出范围");
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    uint8_t byte = buffer[offset];
    
    // 按照协议规范解析位域
    diq->dpi = byte & 0x03;           // Bit 2-1: 双点信息位
    diq->reserved = (byte >> 2) & 0x03; // Bit 4-3: 保留位
    diq->bl = (byte >> 5) & 0x01;     // Bit 5: 闭锁位
    diq->sb = (byte >> 6) & 0x01;     // Bit 6: 替代位
    diq->nt = (byte >> 7) & 0x01;     // Bit 7: 非当前值位
    diq->iv = (byte >> 8) & 0x01;     // Bit 8: 无效位
    
    LOG_DEBUG(LOG_MODULE_NAME, "DIQ解析: 0x%02X -> DPI=%d, BL=%d, SB=%d, NT=%d, IV=%d", 
              byte, diq->dpi, diq->bl, diq->sb, diq->nt, diq->iv);
    
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 构建DIQ品质描述符
 * @details 将DIQ结构转换为字节流，按照协议规范构建各个位域
 * 
 * @param diq DIQ结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param offset 偏移量
 * @return 协议错误码
 */
protocol_error_t build_diq(const diq_t* diq, uint8_t* buffer, size_t offset) {
    if (diq == NULL || buffer == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    uint8_t byte = 0;
    
    // 按照协议规范构建位域
    byte |= (diq->dpi & 0x03);                    // Bit 2-1: 双点信息位
    byte |= ((diq->reserved & 0x03) << 2);        // Bit 4-3: 保留位
    byte |= ((diq->bl & 0x01) << 5);              // Bit 5: 闭锁位
    byte |= ((diq->sb & 0x01) << 6);              // Bit 6: 替代位
    byte |= ((diq->nt & 0x01) << 7);              // Bit 7: 非当前值位
    byte |= ((diq->iv & 0x01) << 8);              // Bit 8: 无效位
    
    buffer[offset] = byte;
    
    LOG_DEBUG(LOG_MODULE_NAME, "DIQ构建: DPI=%d, BL=%d, SB=%d, NT=%d, IV=%d -> 0x%02X", 
              diq->dpi, diq->bl, diq->sb, diq->nt, diq->iv, byte);
    
    return PROTOCOL_SUCCESS;
}

/* ==================== QDS处理函数实现 ==================== */

/**
 * @brief 解析QDS品质描述符
 * @details 从字节流中解析QDS品质描述符，按照协议规范解析各个位域
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param offset 偏移量
 * @param qds QDS结构输出，不能为NULL
 * @return 协议错误码
 */
protocol_error_t parse_qds(const uint8_t* buffer, size_t buffer_size, size_t offset, qds_t* qds) {
    if (buffer == NULL || qds == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (offset >= buffer_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区偏移量超出范围");
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    uint8_t byte = buffer[offset];
    
    // 按照协议规范解析位域
    qds->ov = byte & 0x01;           // Bit 1: 溢出位
    qds->reserved = (byte >> 1) & 0x07; // Bit 4-2: 保留位
    qds->bl = (byte >> 5) & 0x01;     // Bit 5: 闭锁位
    qds->sb = (byte >> 6) & 0x01;     // Bit 6: 替代位
    qds->nt = (byte >> 7) & 0x01;     // Bit 7: 非当前值位
    qds->iv = (byte >> 8) & 0x01;     // Bit 8: 无效位
    
    LOG_DEBUG(LOG_MODULE_NAME, "QDS解析: 0x%02X -> OV=%d, BL=%d, SB=%d, NT=%d, IV=%d", 
              byte, qds->ov, qds->bl, qds->sb, qds->nt, qds->iv);
    
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 构建QDS品质描述符
 * @details 将QDS结构转换为字节流，按照协议规范构建各个位域
 * 
 * @param qds QDS结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param offset 偏移量
 * @return 协议错误码
 */
protocol_error_t build_qds(const qds_t* qds, uint8_t* buffer, size_t offset) {
    if (qds == NULL || buffer == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    uint8_t byte = 0;
    
    // 按照协议规范构建位域
    byte |= (qds->ov & 0x01);                     // Bit 1: 溢出位
    byte |= ((qds->reserved & 0x07) << 1);        // Bit 4-2: 保留位
    byte |= ((qds->bl & 0x01) << 5);              // Bit 5: 闭锁位
    byte |= ((qds->sb & 0x01) << 6);              // Bit 6: 替代位
    byte |= ((qds->nt & 0x01) << 7);              // Bit 7: 非当前值位
    byte |= ((qds->iv & 0x01) << 8);              // Bit 8: 无效位
    
    buffer[offset] = byte;
    
    LOG_DEBUG(LOG_MODULE_NAME, "QDS构建: OV=%d, BL=%d, SB=%d, NT=%d, IV=%d -> 0x%02X", 
              qds->ov, qds->bl, qds->sb, qds->nt, qds->iv, byte);
    
    return PROTOCOL_SUCCESS;
}

/* ==================== DCO处理函数实现 ==================== */

/**
 * @brief 解析DCO双点遥控信息元素
 * @details 从字节流中解析DCO双点遥控信息元素，按照协议规范解析各个位域
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param offset 偏移量
 * @param dco DCO结构输出，不能为NULL
 * @return 协议错误码
 */
protocol_error_t parse_dco(const uint8_t* buffer, size_t buffer_size, size_t offset, dco_t* dco) {
    if (buffer == NULL || dco == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (offset >= buffer_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区偏移量超出范围");
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    uint8_t byte = buffer[offset];
    
    // 按照协议规范解析位域
    dco->dcs = byte & 0x03;           // Bit 2-1: 双点命令状态
    dco->qu = (byte >> 2) & 0x1F;     // Bit 7-3: 限定词
    dco->se = (byte >> 7) & 0x01;     // Bit 8: 选择/执行
    
    LOG_DEBUG(LOG_MODULE_NAME, "DCO解析: 0x%02X -> DCS=%d, QU=%d, S/E=%d", 
              byte, dco->dcs, dco->qu, dco->se);
    
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 构建DCO双点遥控信息元素
 * @details 将DCO结构转换为字节流，按照协议规范构建各个位域
 * 
 * @param dco DCO结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param offset 偏移量
 * @return 协议错误码
 */
protocol_error_t build_dco(const dco_t* dco, uint8_t* buffer, size_t offset) {
    if (dco == NULL || buffer == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    uint8_t byte = 0;
    
    // 按照协议规范构建位域
    byte |= (dco->dcs & 0x03);                    // Bit 2-1: 双点命令状态
    byte |= ((dco->qu & 0x1F) << 2);              // Bit 7-3: 限定词
    byte |= ((dco->se & 0x01) << 7);              // Bit 8: 选择/执行
    
    buffer[offset] = byte;
    
    LOG_DEBUG(LOG_MODULE_NAME, "DCO构建: DCS=%d, QU=%d, S/E=%d -> 0x%02X", 
              dco->dcs, dco->qu, dco->se, byte);
    
    return PROTOCOL_SUCCESS;
}

/* ==================== 品质描述符验证函数实现 ==================== */

/**
 * @brief 验证SIQ品质描述符
 * @details 验证SIQ品质描述符的各个位域是否有效
 * 
 * @param siq SIQ结构，不能为NULL
 * @return 协议错误码
 */
protocol_error_t validate_siq(const siq_t* siq) {
    if (siq == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    // 验证保留位必须为0
    if (siq->reserved != 0) {
        LOG_WARN(LOG_MODULE_NAME, "SIQ保留位不为0: %d", siq->reserved);
    }
    
    // 验证位域值范围
    // 注意: 1位位域(spi, bl, sb, nt, iv)的范围已被类型限制为0-1，无需检查
    // if (siq->spi > 1 || siq->bl > 1 || siq->sb > 1 || siq->nt > 1 || siq->iv > 1) { ... } // 已移除，总是为假
    
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证DIQ品质描述符
 * @details 验证DIQ品质描述符的各个位域是否有效
 * 
 * @param diq DIQ结构，不能为NULL
 * @return 协议错误码
 */
protocol_error_t validate_diq(const diq_t* diq) {
    if (diq == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    // 验证保留位必须为0
    if (diq->reserved != 0) {
        LOG_WARN(LOG_MODULE_NAME, "DIQ保留位不为0: %d", diq->reserved);
    }
    
    // 验证DPI值范围 (0-3)
    // 注意: dpi是2位位域，范围已被类型限制为0-3，无需检查
    // if (diq->dpi > 3) { ... } // 已移除，总是为假
    
    // 验证位域值范围
    // 注意: 1位位域(bl, sb, nt, iv)的范围已被类型限制为0-1，无需检查
    // if (diq->bl > 1 || diq->sb > 1 || diq->nt > 1 || diq->iv > 1) { ... } // 已移除，总是为假
    
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证QDS品质描述符
 * @details 验证QDS品质描述符的各个位域是否有效
 * 
 * @param qds QDS结构，不能为NULL
 * @return 协议错误码
 */
protocol_error_t validate_qds_descriptor(const qds_t* qds) {
    if (qds == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    // 验证保留位必须为0
    if (qds->reserved != 0) {
        LOG_WARN(LOG_MODULE_NAME, "QDS保留位不为0: %d", qds->reserved);
    }
    
    // 验证位域值范围
    // 注意: 1位位域(ov, bl, sb, nt, iv)的范围已被类型限制为0-1，无需检查
    // if (qds->ov > 1 || qds->bl > 1 || qds->sb > 1 || qds->nt > 1 || qds->iv > 1) { ... } // 已移除，总是为假
    
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证DCO双点遥控信息元素
 * @details 验证DCO双点遥控信息元素的各个位域是否有效
 * 
 * @param dco DCO结构，不能为NULL
 * @return 协议错误码
 */
protocol_error_t validate_dco(const dco_t* dco) {
    if (dco == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    // 验证DCS值范围 (0-3)
    // 注意: dcs是2位位域，范围已被类型限制为0-3，无需检查
    // if (dco->dcs > 3) { ... } // 已移除，总是为假
    
    // 验证QU值范围 (0-31)
    // 注意: qu是5位位域，范围已被类型限制为0-31，无需检查
    // if (dco->qu > 31) { ... } // 已移除，总是为假
    
    // 验证S/E位域值范围
    // 注意: se是1位位域，范围已被类型限制为0-1，无需检查
    // if (dco->se > 1) { ... } // 已移除，总是为假
    
    return PROTOCOL_SUCCESS;
}
